package com.jackwei.leetcode.offer.sword;

import java.util.Scanner;
import java.util.Stack;

/**
 * @author Jack
 * @date 2021-12-10
 *
 * 剑指 Offer 30. 包含min函数的栈
 * 定义栈的数据结构，请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中，
 * 调用 min、push 及 pop 的时间复杂度都是 O(1)。

 * 示例:
 *
 * MinStack minStack = new MinStack();
 * minStack.push(-2);
 * minStack.push(0);
 * minStack.push(-3);
 * minStack.min();   --> 返回 -3.
 * minStack.pop();
 * minStack.top();      --> 返回 0.
 * minStack.min();   --> 返回 -2.
 *  
 * 提示：
 *
 * 各函数的调用总次数不超过 20000 次
 *
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/bao-han-minhan-shu-de-zhan-lcof
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 */
public class O030 {
}
class MinStack {

    private Stack<Integer> stack;
    private Integer min = Integer.MAX_VALUE;
    /** 初始化*/
    public MinStack() {
        stack = new Stack<>();
    }

    /**
     * 压入栈
     */
    public void push(int x) {
        // 上来先把最小值压进去，保证最顶端的值是最小值
        stack.push(min);
        // 判断新值是否是最小的
        if (x < min) {
            min = x;
        }
        // 然后把新值压进去
        stack.push(x);
    }

    /**
     * 正常弹出即可
     */
    public void pop() {
        // 注意要把新值弹出去
        stack.pop();
        // 接下来得到的是最小值
        min = stack.peek();
        // 因为之前我们先把最小值压进去，所以要弹出两次
        stack.pop();
    }

    /**
     * 获取栈顶的数据
     */
    public int top() {
        return stack.peek();
    }

    /**
     * 获取最小值
     */
    public int min() {
        return min;
    }

    public static void main(String[] args) {
        // 输入指令那一行数据如：["MinStack","push","push","push","min","pop","top","min"]
        Scanner scanner = new Scanner(System.in);
        String inputStr = scanner.next();
        // 去头去尾，替换“并处理成： MinStack,push,push,push,min,pop,top,min
        inputStr = inputStr.substring(1, inputStr.length() - 1).replaceAll("\"", "");
        String[] commends = inputStr.split(",");

        // 输入代码对应的值:[[],[-2],[0],[-3],[],[],[],[]]
        String valueStr = scanner.next();
        // 去头去尾即可：[],[-2],[0],[-3],[],[],[],[]
        valueStr = valueStr.substring(1, valueStr.length() - 1);
        String[] values = valueStr.split(",");

        MinStack minStack = null;

        // 存放最终的结果
        StringBuilder result = new StringBuilder();
        result.append("[");

        for (int i = 0; i < commends.length; i++) {
            String commend = commends[i];
            String value = values[i];
            // 对应处理指令
            switch (commend) {
                // 初始化
                case "MinStack":
                    minStack = new MinStack();
                    result.append("null,");
                    break;
                // 入栈
                case "push":
                    // 去头去尾，拿到中括号里面数字
                    String num = value.substring(1, value.length() - 1);
                    minStack.push(Integer.parseInt(num));
                    result.append("null,");
                    break;
                // 获取最小值
                case "min":
                    int min = minStack.min();
                    result.append(min+",");
                    break;
                // 出栈
                case "pop":
                    minStack.pop();
                    result.append("null,");
                    break;
                // 栈顶数据
                case "top":
                    int top = minStack.top();
                    result.append(top+",");
                    break;
                default:
            }
        }
        // 去除最后一个逗号，
        String resultStr = result.substring(0, result.length() - 1);
        System.out.println(resultStr+"]");
    }
}